<template>
  <div class="hello">
    <h1>子组件显示父组件的信息：{{ msg }}</h1>
    <h3>父组件传过来的数据------{{ msgList }}</h3>
    <h4>watch监听数据-----{{ watchVal }}</h4>
    <el-button type="success" @click="sonClick">子传父的方法</el-button>
    <el-button type="primary" @click="sendMittData">通过$mitt发送数据</el-button>
    <el-button type="primary" @click="watchClick">测试监听数据</el-button>
  </div>
</template>

<script setup>
import { ref, reactive, getCurrentInstance, watch, watchEffect } from "vue";

// -----------父传子的方法defineProps--------------------------------

// let props = defineProps(["msg"]);
let props = defineProps({
  msg: {
    type: String, // 类型
    default: () => "", // 默认值
    required: true, // 是否必传
  },
  msgList: {
    type: Array, // 类型
    default: () => [], // 默认值
    required: true, // 是否必传
  },
});
console.log("父传子的方法defineProps-----值", props.msg);

// -------监听--------------------------------------------------------
// immediate：是否立即执行一次
// deep：是否开启深度监听
// watchEffect：不需要明确的去监视谁，谁在回调函数里面用到了，就监视谁。注意：该回调函数一开始会执行一次
let watchVal = ref(1);
let watchValNew = ref("我是重新监听");
let watchClick = () => {
  watchVal.value = "我是有变化的！";
};
let flag = watch(
  watchVal,
  (newVal, oldVal) => {
    console.log("watchVal：监听的数据", `老数据：${oldVal}, 新数据：${newVal} `);
    if (newVal >= 6) {
      // 只要将 flag 声明的函数调用就可以结束监听了
      flag(); // 结束监听,如果想重新启动 则需要重新给watch赋值
    }
  },
  {
    deep: true,
    immediate: true,
  }
);
// 重新启动监听--------------watchEffect同理
flag = watch(
  watchValNew,
  (newVal, oldVal) => {
    console.log("重新启动监听的数据", `老数据：${oldVal}, 新数据：${newVal} `);
  },
  {
    deep: true,
    immediate: true,
  }
);
setTimeout(() => {
  watchVal.value++;
}, 1000);

const watchDemo = reactive({
  name: "前端小玖",
  nickName: "小玖",
  soulmate: {
    name: "",
    nickName: "",
  },
});

// 监听整个对象
watch(watchDemo, (newValue, oldValue) => {
  console.log("watch 已触发", newValue);
});

//------ ()=> 写法只适用于监听数组的某个元素

// 监听对象中的某个属性
// 监听demo对象的name属性
watch(
  () => watchDemo.name,
  (newValue, oldValue) => {
    console.log("watch 已触发", newValue);
  }
);

// 只监听对象的子属性
watch(
  () => ({ ...watchDemo }),
  (newValue, oldValue) => {
    console.log("watch 已触发", newValue);
  }
);

// 监听对象的所有属性
watch(
  () => watchDemo,
  (newValue, oldValue) => {
    console.log("watch 已触发", newValue);
  },
  { deep: true }
);

// 组合监听
const nums = ref(9);
const demo = reactive({
  name: "前端小玖",
  nickName: "小玖",
  soulmate: {
    name: "",
    nickName: "",
  },
});
watch([() => demo.name, nums], ([newName, newNums], [oldName, oldNums]) => {
  console.log("watch 已触发: name", newName);
  console.log("watch 已触发: nums", newNums);
});

// ----------watchEffect---------------
setTimeout(() => {
  watchDemo.name = "前端小王";
}, 1000);
watchEffect(
  () => {
    let m = watchDemo.name;
    let s = watchVal;
    console.log("state.name 变化了", watchDemo.name);
    console.log("watchVal 变化了", watchVal);
  },
  {
    flush: "post", // pre：组件更新前执行;sync：强制效果始终同步触发,post：组件更新后执行
    onTrigger() {
      //onTrigger  可以帮助我们调试 watchEffect
    },
  }
);

// -------子传父的方法defineEmits--------------------------------------
const emit = defineEmits(["clickFu"]);
let sonClick = () => {
  emit("clickFu", "我是子传父的数据呀1111111");
};

// -------暴露子组件元素的方法defineExpose（方便父组件调用子组件的方法以及属性值）------------------------------
let df = ref("我是谁哦");
let sonMethods = () => {
  alert("我是子组件的方法");
};
// 父组件调用子组件的方法以及调用其子组件的属性值
defineExpose({
  count: 1,
  df: df.value,
  sonMethods,
});

// ------子传子的方法(安装mitt：npm install --save mitt（兄弟组件传值（ 借助mitt ）–全局引入）)--------------------------------------------------
let { proxy } = getCurrentInstance(); // vue3取消了this，调用全局的方法， 获取当前组件的实例、上下文来操作router和vuex等。
let money = ref(100);
let sendMittData = () => {
  proxy.$mitt.emit("sendMittData", money.value);
  console.log(proxy.$mitt, "proxy.$mitt");
};
</script>

<style scoped lang="scss"></style>
